home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / python2.6 / email / generator.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  9.8 KB  |  293 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''Classes to generate plain text from a message object tree.'''
  5. __all__ = [
  6.     'Generator',
  7.     'DecodedGenerator']
  8. import re
  9. import sys
  10. import time
  11. import random
  12. import warnings
  13. from cStringIO import StringIO
  14. from email.header import Header
  15. UNDERSCORE = '_'
  16. NL = '\n'
  17. fcre = re.compile('^From ', re.MULTILINE)
  18.  
  19. def _is8bitstring(s):
  20.     if isinstance(s, str):
  21.         
  22.         try:
  23.             unicode(s, 'us-ascii')
  24.         except UnicodeError:
  25.             return True
  26.         
  27.  
  28.     None<EXCEPTION MATCH>UnicodeError
  29.     return False
  30.  
  31.  
  32. class Generator:
  33.     '''Generates output from a Message object tree.
  34.  
  35.     This basic generator writes the message to the given file object as plain
  36.     text.
  37.     '''
  38.     
  39.     def __init__(self, outfp, mangle_from_ = True, maxheaderlen = 78):
  40.         """Create the generator for message flattening.
  41.  
  42.         outfp is the output file-like object for writing the message to.  It
  43.         must have a write() method.
  44.  
  45.         Optional mangle_from_ is a flag that, when True (the default), escapes
  46.         From_ lines in the body of the message by putting a `>' in front of
  47.         them.
  48.  
  49.         Optional maxheaderlen specifies the longest length for a non-continued
  50.         header.  When a header line is longer (in characters, with tabs
  51.         expanded to 8 spaces) than maxheaderlen, the header will split as
  52.         defined in the Header class.  Set maxheaderlen to zero to disable
  53.         header wrapping.  The default is 78, as recommended (but not required)
  54.         by RFC 2822.
  55.         """
  56.         self._fp = outfp
  57.         self._mangle_from_ = mangle_from_
  58.         self._maxheaderlen = maxheaderlen
  59.  
  60.     
  61.     def write(self, s):
  62.         self._fp.write(s)
  63.  
  64.     
  65.     def flatten(self, msg, unixfrom = False):
  66.         """Print the message object tree rooted at msg to the output file
  67.         specified when the Generator instance was created.
  68.  
  69.         unixfrom is a flag that forces the printing of a Unix From_ delimiter
  70.         before the first object in the message tree.  If the original message
  71.         has no From_ delimiter, a `standard' one is crafted.  By default, this
  72.         is False to inhibit the printing of any From_ delimiter.
  73.  
  74.         Note that for subobjects, no From_ line is printed.
  75.         """
  76.         if unixfrom:
  77.             ufrom = msg.get_unixfrom()
  78.             if not ufrom:
  79.                 ufrom = 'From nobody ' + time.ctime(time.time())
  80.             
  81.             print >>self._fp, ufrom
  82.         
  83.         self._write(msg)
  84.  
  85.     
  86.     def clone(self, fp):
  87.         '''Clone this generator with the exact same options.'''
  88.         return self.__class__(fp, self._mangle_from_, self._maxheaderlen)
  89.  
  90.     
  91.     def _write(self, msg):
  92.         oldfp = self._fp
  93.         
  94.         try:
  95.             self._fp = sfp = StringIO()
  96.             self._dispatch(msg)
  97.         finally:
  98.             self._fp = oldfp
  99.  
  100.         meth = getattr(msg, '_write_headers', None)
  101.         if meth is None:
  102.             self._write_headers(msg)
  103.         else:
  104.             meth(self)
  105.         self._fp.write(sfp.getvalue())
  106.  
  107.     
  108.     def _dispatch(self, msg):
  109.         main = msg.get_content_maintype()
  110.         sub = msg.get_content_subtype()
  111.         specific = UNDERSCORE.join((main, sub)).replace('-', '_')
  112.         meth = getattr(self, '_handle_' + specific, None)
  113.         if meth is None:
  114.             generic = main.replace('-', '_')
  115.             meth = getattr(self, '_handle_' + generic, None)
  116.             if meth is None:
  117.                 meth = self._writeBody
  118.             
  119.         
  120.         meth(msg)
  121.  
  122.     
  123.     def _write_headers(self, msg):
  124.         for h, v in msg.items():
  125.             print >>self._fp, '%s:' % h,
  126.             if self._maxheaderlen == 0:
  127.                 print >>self._fp, v
  128.                 continue
  129.             if isinstance(v, Header):
  130.                 print >>self._fp, v.encode()
  131.                 continue
  132.             if _is8bitstring(v):
  133.                 print >>self._fp, v
  134.                 continue
  135.             print >>self._fp, Header(v, maxlinelen = self._maxheaderlen, header_name = h, continuation_ws = '\t').encode()
  136.         
  137.         print >>self._fp
  138.  
  139.     
  140.     def _handle_text(self, msg):
  141.         payload = msg.get_payload()
  142.         if payload is None:
  143.             return None
  144.         if not isinstance(payload, basestring):
  145.             raise TypeError('string payload expected: %s' % type(payload))
  146.         isinstance(payload, basestring)
  147.         if self._mangle_from_:
  148.             payload = fcre.sub('>From ', payload)
  149.         
  150.         self._fp.write(payload)
  151.  
  152.     _writeBody = _handle_text
  153.     
  154.     def _handle_multipart(self, msg):
  155.         msgtexts = []
  156.         subparts = msg.get_payload()
  157.         if subparts is None:
  158.             subparts = []
  159.         elif isinstance(subparts, basestring):
  160.             self._fp.write(subparts)
  161.             return None
  162.         if not isinstance(subparts, list):
  163.             subparts = [
  164.                 subparts]
  165.         
  166.         for part in subparts:
  167.             s = StringIO()
  168.             g = self.clone(s)
  169.             g.flatten(part, unixfrom = False)
  170.             msgtexts.append(s.getvalue())
  171.         
  172.         alltext = NL.join(msgtexts)
  173.         boundary = msg.get_boundary(failobj = _make_boundary(alltext))
  174.         if msg.get_boundary() != boundary:
  175.             msg.set_boundary(boundary)
  176.         
  177.         if msg.preamble is not None:
  178.             print >>self._fp, msg.preamble
  179.         
  180.         print >>self._fp, '--' + boundary
  181.         if msgtexts:
  182.             self._fp.write(msgtexts.pop(0))
  183.         
  184.         for body_part in msgtexts:
  185.             print >>self._fp, '\n--' + boundary
  186.             self._fp.write(body_part)
  187.         
  188.         self._fp.write('\n--' + boundary + '--')
  189.         if msg.epilogue is not None:
  190.             print >>self._fp
  191.             self._fp.write(msg.epilogue)
  192.         
  193.  
  194.     
  195.     def _handle_message_delivery_status(self, msg):
  196.         blocks = []
  197.         for part in msg.get_payload():
  198.             s = StringIO()
  199.             g = self.clone(s)
  200.             g.flatten(part, unixfrom = False)
  201.             text = s.getvalue()
  202.             lines = text.split('\n')
  203.             if lines and lines[-1] == '':
  204.                 blocks.append(NL.join(lines[:-1]))
  205.                 continue
  206.             blocks.append(text)
  207.         
  208.         self._fp.write(NL.join(blocks))
  209.  
  210.     
  211.     def _handle_message(self, msg):
  212.         s = StringIO()
  213.         g = self.clone(s)
  214.         g.flatten(msg.get_payload(0), unixfrom = False)
  215.         self._fp.write(s.getvalue())
  216.  
  217.  
  218. _FMT = '[Non-text (%(type)s) part of message omitted, filename %(filename)s]'
  219.  
  220. class DecodedGenerator(Generator):
  221.     '''Generator a text representation of a message.
  222.  
  223.     Like the Generator base class, except that non-text parts are substituted
  224.     with a format string representing the part.
  225.     '''
  226.     
  227.     def __init__(self, outfp, mangle_from_ = True, maxheaderlen = 78, fmt = None):
  228.         """Like Generator.__init__() except that an additional optional
  229.         argument is allowed.
  230.  
  231.         Walks through all subparts of a message.  If the subpart is of main
  232.         type `text', then it prints the decoded payload of the subpart.
  233.  
  234.         Otherwise, fmt is a format string that is used instead of the message
  235.         payload.  fmt is expanded with the following keywords (in
  236.         %(keyword)s format):
  237.  
  238.         type       : Full MIME type of the non-text part
  239.         maintype   : Main MIME type of the non-text part
  240.         subtype    : Sub-MIME type of the non-text part
  241.         filename   : Filename of the non-text part
  242.         description: Description associated with the non-text part
  243.         encoding   : Content transfer encoding of the non-text part
  244.  
  245.         The default value for fmt is None, meaning
  246.  
  247.         [Non-text (%(type)s) part of message omitted, filename %(filename)s]
  248.         """
  249.         Generator.__init__(self, outfp, mangle_from_, maxheaderlen)
  250.         if fmt is None:
  251.             self._fmt = _FMT
  252.         else:
  253.             self._fmt = fmt
  254.  
  255.     
  256.     def _dispatch(self, msg):
  257.         for part in msg.walk():
  258.             maintype = part.get_content_maintype()
  259.             if maintype == 'text':
  260.                 print >>self, part.get_payload(decode = True)
  261.                 continue
  262.             if maintype == 'multipart':
  263.                 continue
  264.             print >>self, self._fmt % {
  265.                 'type': part.get_content_type(),
  266.                 'maintype': part.get_content_maintype(),
  267.                 'subtype': part.get_content_subtype(),
  268.                 'filename': part.get_filename('[no filename]'),
  269.                 'description': part.get('Content-Description', '[no description]'),
  270.                 'encoding': part.get('Content-Transfer-Encoding', '[no encoding]') }
  271.         
  272.  
  273.  
  274. _width = len(repr(sys.maxint - 1))
  275. _fmt = '%%0%dd' % _width
  276.  
  277. def _make_boundary(text = None):
  278.     token = random.randrange(sys.maxint)
  279.     boundary = '===============' + _fmt % token + '=='
  280.     if text is None:
  281.         return boundary
  282.     b = boundary
  283.     counter = 0
  284.     while True:
  285.         cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE)
  286.         if not cre.search(text):
  287.             break
  288.         
  289.         b = boundary + '.' + str(counter)
  290.         counter += 1
  291.     return b
  292.  
  293.